﻿using CGT.API.Models;
using Newtonsoft.Json.Linq;
using OF.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace CGT.API.Common
{
    /// <summary>
    /// 腾讯AI
    /// </summary>
    public class TencentAI
    {
        /// <summary>
        /// 腾讯appid
        /// </summary>
        protected string AppId = ConfigHelper.GetValue("TencentAI.AppId");

        /// <summary>
        /// 腾讯appkey
        /// </summary>
        protected string AppKey = ConfigHelper.GetValue("TencentAI.AppKey");

        #region 腾讯api

        /// <summary>
        /// 语音识别-echo版
        /// 对音频进行语音识别，并返回语音的文字内容
        /// </summary>
        /// <returns></returns>
        public string aai_asr(string filePath)
        {
            Dictionary<string, string> dicParams = new Dictionary<string, string>();
            dicParams.Add("app_id", AppId);
            dicParams.Add("format", "2");
            dicParams.Add("rate", "16000");
            dicParams.Add("speech", FileToBase64(filePath));
            dicParams.Add("time_stamp", GenerateTimeStamp());
            dicParams.Add("nonce_str", GenerateNonceStr());

            dicParams.Add("sign", getReqSign(dicParams, AppKey));

            string url = "https://api.ai.qq.com/fcgi-bin/aai/aai_asr";
            return HttpWebRequestService.GetRequest(url, DictoryToParam(dicParams), "POST", "", null);
        }

        /// <summary>
        /// 根据用户上传的包含身份证正反面照片，识别并且获取证件姓名、性别、民族、出生日期、地址、身份证号、证件有效期、发证机关等详细的身份证信息，并且可以返回精确剪裁对齐后的身份证正反面图片。
        /// </summary>
        /// <param name="filePath">身份证地址</param>
        /// <param name="cardType">身份证正反面 0:证明 1：反面</param>
        /// <returns></returns>
        public string ocr_idcardocr(string filePath, string cardType)
        {
            Dictionary<string, string> dicParams = new Dictionary<string, string>();
            dicParams.Add("app_id", "2110264734");
            dicParams.Add("card_type", cardType);
            dicParams.Add("image", FileToBase64(filePath));
            dicParams.Add("time_stamp", GenerateTimeStamp());
            dicParams.Add("nonce_str", GenerateNonceStr());

            dicParams.Add("sign", getReqSign(dicParams, AppKey));


            string url = "https://api.ai.qq.com/fcgi-bin/ocr/ocr_idcardocr";
            return HttpWebRequestService.GetRequest(url, DictoryToParam(dicParams), "POST", "", null);
        }

        /// <summary>
        /// 语音合成
        /// </summary>
        /// <returns></returns>
        public string aai_tts()
        {
            Dictionary<string, string> dicParams = new Dictionary<string, string>();
            dicParams.Add("app_id", AppId);
            dicParams.Add("speaker", "6");
            dicParams.Add("format", "3");
            dicParams.Add("volume", "5");
            dicParams.Add("speed", "100");  //语速
            dicParams.Add("text", "12358");    //文本内容
            dicParams.Add("aht", "0");      //语音
            dicParams.Add("apc", "60");     //频谱翘曲的
            dicParams.Add("time_stamp", GenerateTimeStamp());
            dicParams.Add("nonce_str", GenerateNonceStr());


            dicParams.Add("sign", getReqSign(dicParams, AppKey));

            string url = "https://api.ai.qq.com/fcgi-bin/aai/aai_tts";
            return HttpWebRequestService.GetRequest(url, DictoryToParam(dicParams), "POST", "", null);
        }

        /// <summary>
        /// 人脸对比
        /// </summary>
        /// <param name="img1"></param>
        /// <param name="img2"></param>
        /// <returns></returns>
        public string face_facecompare(string img1, string img2)
        {
            Dictionary<string, string> dicParams = new Dictionary<string, string>();
            dicParams.Add("app_id", AppId);
            dicParams.Add("image_a", FileToBase64(img1));
            dicParams.Add("image_b", FileToBase64(img2));
            dicParams.Add("time_stamp", GenerateTimeStamp());
            dicParams.Add("nonce_str", GenerateNonceStr());


            dicParams.Add("sign", getReqSign(dicParams, AppKey));

            string url = "https://api.ai.qq.com/fcgi-bin/face/face_facecompare";
            return HttpWebRequestService.GetRequest(url, DictoryToParam(dicParams), "POST", "", null);
        }

        /// <summary>
        /// 解析身份识别
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public ResultData<IdcardOCRModel> ParseIdCardResult(string str)
        {
            ResultData<IdcardOCRModel> result = new ResultData<IdcardOCRModel>();
            IdcardOCRModel model = new IdcardOCRModel();
            result.data = model;

            try
            {
                JObject jobj = JObject.Parse(str);
                foreach (JProperty jpr in jobj.Properties())
                {
                    switch (jpr.Name)
                    {
                        case "ret":
                            int ret = jobj["ret"].Value<int>();  //0代表成功
                            result.status = ret;
                            break;
                        case "msg":
                            result.message = jobj["msg"].Value<string>();
                            break;
                        case "data":
                            if (jobj["data"].Type == JTokenType.Null || !jobj["data"].HasValues)
                            {
                                continue;
                            }
                            else if (jobj["data"].HasValues)
                            {
                                JToken jt = jobj["data"];
                                model.Name = jt.Value<string>("name");
                                model.Sex = jt.Value<string>("sex");
                                model.Nation = jt.Value<string>("nation");
                                model.Birth = jt.Value<string>("birth");
                                model.Address = jt.Value<string>("address");
                                model.Id = jt.Value<string>("id");
                                model.Authority = jt.Value<string>("authority");
                                model.ValidDate = jt.Value<string>("valid_date");
                            }
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                result.status = -1;
                result.message = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// 解析语音识别
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public ResultData<ASRModel> ParseASRResult(string str)
        {
            ResultData<ASRModel> result = new ResultData<ASRModel>();
            ASRModel model = new ASRModel();
            result.data = model;

            JObject jobj = JObject.Parse(str);
            foreach (JProperty jpr in jobj.Properties())
            {
                switch (jpr.Name)
                {
                    case "ret":
                        int ret = jobj["ret"].Value<int>();  //0代表成功
                        result.status = ret;
                        break;
                    case "msg":
                        result.message = jobj["msg"].Value<string>();
                        break;
                    case "data":
                        if (jobj["data"].Type == JTokenType.Null || !jobj["data"].HasValues)
                        {
                            continue;
                        }
                        else if (jobj["data"].HasValues)
                        {
                            JToken jt = jobj["data"];
                            model.Format = jt.Value<int>("format");
                            model.Rate = jt.Value<int>("rate");
                            model.Text = jt.Value<string>("text");
                        }
                        break;
                }
            }
            return result;
        }



        /// <summary>
        /// 解析人脸对比
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public ResultData<FaceCompareModel> ParseFaceCompareResult(string str)
        {
            ResultData<FaceCompareModel> result = new ResultData<FaceCompareModel>();
            FaceCompareModel model = new FaceCompareModel();
            result.data = model;

            JObject jobj = JObject.Parse(str);
            foreach (JProperty jpr in jobj.Properties())
            {
                switch (jpr.Name)
                {
                    case "ret":
                        int ret = jobj["ret"].Value<int>();  //0代表成功
                        result.status = ret;
                        break;
                    case "msg":
                        result.message = jobj["msg"].Value<string>();
                        break;
                    case "data":
                        if (jobj["data"].Type == JTokenType.Null || !jobj["data"].HasValues)
                        {
                            continue;
                        }
                        else if (jobj["data"].HasValues)
                        {
                            JToken jt = jobj["data"];
                            model.FailFlag = jt.Value<int>("fail_flag");
                            model.Similarity = jt.Value<float>("similarity");
                        }
                        break;
                }
            }
            return result;
        }
        #endregion

        #region 辅助方法

        /// <summary>
        /// JavaUrlEncode
        /// </summary>
        /// <param name="strCode">待转码字符串</param>
        /// <returns></returns>
        public string UrlEncode(string strCode)
        {
            StringBuilder sb = new StringBuilder();
            byte[] byStr = Encoding.UTF8.GetBytes(strCode); //默认是System.Text.Encoding.Default.GetBytes(str)
            System.Text.RegularExpressions.Regex regKey = new System.Text.RegularExpressions.Regex("^[A-Za-z0-9]+$");
            for (int i = 0; i < byStr.Length; i++)
            {
                string strBy = Convert.ToChar(byStr[i]).ToString();
                if (regKey.IsMatch(strBy))
                {
                    //是字母或者数字则不进行转换  
                    sb.Append(strBy);
                }
                else
                {
                    sb.Append(@"%" + Convert.ToString(byStr[i], 16).ToUpper());//javaEncode（urlencode大写）
                }
            }
            return (sb.ToString());
        }

        /// <summary>
        /// 数组转换成参数
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        protected string DictoryToParam(Dictionary<string, string> dic)
        {
            string str = "";
            foreach (var kvp in dic)
            {
                if (!string.IsNullOrEmpty(kvp.Value))
                {
                    str += "&" + kvp.Key + "=" + UrlEncode(kvp.Value);
                }
            }
            return str.Substring(1);
        }

        /// <summary>
        /// 文件读取成base64
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        protected string FileToBase64(string path)
        {
            byte[] inArray = File.ReadAllBytes(path);
            string str = Convert.ToBase64String(inArray);
            return str;
        }

        /// <summary>
        /// 根据 接口请求参数 和 应用密钥 计算 请求签名
        /// </summary>
        /// <param name="dicParams">接口请求参数（特别注意：不同的接口，参数对一般不一样，请以具体接口要求为准）</param>
        /// <param name="appkey">应用密钥</param>
        protected string getReqSign(Dictionary<string, string> dicParams, string appkey)
        {
            // 1. 字典升序排序
            var kvps = dicParams.OrderBy(t => t.Key);

            // 2. 拼按URL键值对
            string str = "";
            foreach (var kvp in kvps)
            {
                if (!string.IsNullOrEmpty(kvp.Value))
                {
                    str += kvp.Key + "=" + UrlEncode(kvp.Value) + "&";
                }
            }

            // 3. 拼接app_key
            str += "app_key=" + appkey;

            // 4. MD5运算+转换大写，得到请求签名
            string sign = MakeSign(str);
            return sign;
        }

        /// <summary>
        /// MD5签名
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        protected string MakeSign(string str)
        {
            //MD5加密
            var md5 = MD5.Create();
            var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            var sb = new StringBuilder();
            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }
            //所有字符转为大写
            return sb.ToString().ToUpper();
        }

        /// <summary>
        /// 生成时间戳，标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数
        /// </summary>
        /// <returns></returns>
        protected string GenerateTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /// <summary>
        /// 生成随机串，随机串包含字母或数字
        /// </summary>
        /// <returns></returns>
        protected string GenerateNonceStr()
        {
            var ran = new Random();
            return string.Format("{0}{1}{2}", "2110264734", DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(999));
        }

        #endregion
    }
}